/*
类的基本定义与使用
*/
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Greeter = /** @class */ (function () {
    // 构造方法
    function Greeter(message) {
        this.message = message;
    }
    // 一般方法
    Greeter.prototype.greet = function () {
        return 'Hello ' + this.message;
    };
    return Greeter;
}());
// 创建类的实例
var greeter = new Greeter('world');
// 调用实例的方法
console.log(greeter.greet());
/*
类的继承
*/
// class Animal {
//     run(distance: number) {
//         console.log(`Animal run ${distance}m`)
//     }
// }
//
// class Dog extends Animal {
//     cry() {
//         console.log('wang! wang!')
//     }
// }
//
// const dog = new Dog()
// dog.cry()
// dog.run(100) // 可以调用从父中继承得到的方法
// class Animal {
//     name: string
//
//     constructor(name: string) {
//         this.name = name
//     }
//
//     run(distance: number = 0) {
//         console.log(`${this.name} run ${distance}m`)
//     }
//
// }
//
// class Snake extends Animal {
//     constructor(name: string) {
//         // 调用父类型构造方法
//         super(name)
//     }
//
//     // 重写父类型的方法
//     run(distance: number = 5) {
//         console.log('sliding...')
//         super.run(distance)
//     }
// }
//
// class Horse extends Animal {
//     constructor(name: string) {
//         // 调用父类型构造方法
//         super(name)
//     }
//
//     // 重写父类型的方法
//     run(distance: number = 50) {
//         console.log('dashing...')
//         // 调用父类型的一般方法
//         super.run(distance)
//     }
//
//     xxx() {
//         console.log('xxx()')
//     }
// }
//
// const snake = new Snake('sn')
// snake.run()
//
// const horse = new Horse('ho')
// horse.run()
//
// // 父类型引用指向子类型的实例 ==> 多态
// const tom: Animal = new Horse('ho22')
// // @ts-ignore
// tom.run()
//
// /* 如果子类型没有扩展的方法, 可以让子类型引用指向父类型的实例 */
// // @ts-ignore
// const tom3: Snake = new Animal('tom3')
// tom3.run()
// /* 如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例 */
// // const tom2: Horse = new Animal('tom2')
// // tom2.run()
//
//
/*
访问修饰符: 用来描述类内部的属性/方法的可访问性
  public: 默认值, 公开的外部也可以访问
  private: 只能类内部可以访问
  protected: 类内部和子类可以访问
*/
var Animal = /** @class */ (function () {
    function Animal(name) {
        this.name = name;
    }
    Animal.prototype.run = function (distance) {
        if (distance === void 0) { distance = 0; }
        console.log("".concat(this.name, " run ").concat(distance, "m"));
    };
    return Animal;
}());
var Person = /** @class */ (function (_super) {
    __extends(Person, _super);
    function Person() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.age = 18;
        _this.sex = '男';
        return _this;
    }
    Person.prototype.run = function (distance) {
        if (distance === void 0) { distance = 5; }
        console.log('Person jumping...');
        _super.prototype.run.call(this, distance);
    };
    return Person;
}(Animal));
var Student = /** @class */ (function (_super) {
    __extends(Student, _super);
    function Student() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Student.prototype.run = function (distance) {
        if (distance === void 0) { distance = 6; }
        console.log('Student jumping...');
        console.log(this.sex); // 子类能看到父类中受保护的成员
        // console.log(this.age) //  子类看不到父类中私有的成员
        _super.prototype.run.call(this, distance);
    };
    return Student;
}(Person));
console.log(new Person('abc').name); // 公开的可见
// console.log(new Person('abc').sex) // 受保护的不可见
// console.log(new Person('abc').age) //  私有的不可见
var Person1 = /** @class */ (function () {
    function Person1(name) {
        this.name = 'abc';
        this.name = name;
    }
    return Person1;
}());
var john = new Person1('John');
// john.name = 'peter' // error
var Person2 = /** @class */ (function () {
    function Person2(name) {
        this.name = name;
    }
    return Person2;
}());
var p = new Person2('jack');
console.log(p.name);
var Person3 = /** @class */ (function () {
    function Person3() {
        this.firstName = 'A';
        this.lastName = 'B';
    }
    Object.defineProperty(Person3.prototype, "fullName", {
        get: function () {
            return this.firstName + '-' + this.lastName;
        },
        set: function (value) {
            var names = value.split('-');
            this.firstName = names[0];
            this.lastName = names[1];
        },
        enumerable: false,
        configurable: true
    });
    return Person3;
}());
var p1 = new Person3();
console.log(p1.fullName);
p1.firstName = 'C';
p1.lastName = 'D';
console.log(p1.fullName);
p1.fullName = 'E-F';
console.log(p1.firstName, p1.lastName);
var Person4 = /** @class */ (function () {
    function Person4() {
        this.name1 = 'A';
    }
    Person4.name2 = 'B';
    return Person4;
}());
console.log(Person4.name2);
console.log(new Person4().name1);
/*
抽象类
  不能创建实例对象, 只有实现类才能创建实例
  可以包含未实现的抽象方法
*/
var Animal2 = /** @class */ (function () {
    function Animal2() {
    }
    Animal2.prototype.run = function () {
        console.log('run()');
    };
    return Animal2;
}());
var Dog = /** @class */ (function (_super) {
    __extends(Dog, _super);
    function Dog() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Dog.prototype.cry = function () {
        console.log(' Dog cry()');
    };
    return Dog;
}(Animal2));
var dog = new Dog();
dog.cry();
dog.run();
